package lk.icta.core.dao;

import lk.icta.core.entity.Land;
import lk.icta.user.entity.User;
import org.hibernate.exception.DataException;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author Duminda Dharmakeerthi
 */
public interface LandDAO {
    /**
     * Add a Land
     *
     * @param land The land to be added
     * @param user User requesting to add the land
     */
    public void addLand(Land land, User user);

    /**
     * Updating a land
     *
     * @param land The land to be updated
     * @param user User requesting to update the land
     */
    public void updateLand(Land land, User user);

    /**
     * Deleting a land (ARCHIVED)
     *
     * @param land Land to be deleted
     * @param user User requesting to delete the land
     */
    public void deleteLand(Land land, User user);

    public void deleteLandFromDatabase(long landId, User user);

    /**
     * Returns a land corresponding to the given land id
     *
     * @param idUKey Id of the land
     * @param user   User requesting to search the land
     * @return The land corresponding to the given id
     */
    public Land getLandByIdUKey(long idUKey, User user);

    /**
     * Returns list of lands having the given land name
     *
     * @param nameOfTheLand The name of the land
     * @param user          User requesting to search the land
     * @return List of lands with the given name
     */
    public List<Land> getLandByName(String nameOfTheLand, User user);

    /**
     * Returns list of lands within a given GNDivision
     *
     * @param gnDivisionId Id of the GNDivision
     * @param user         User requesting to list the lands
     * @return List of lands within the given GNDivision
     */
    public List<Land> getLandsByGNDivision(int gnDivisionId, User user);

    /**
     * Returns list of lands within a given GNDivision which are not ARCHIVED
     *
     * @param gnDivisionId Id of the GNDivision
     * @param user         User requesting to list the lands
     * @return List of lands within the given GNDivision
     */
    public List<Land> getActiveLandsByGNDivision(int gnDivisionId, User user);

    /**
     * Returns list of lands within a given GNDivision which are in initial state
     *
     * @param gnDivisionId ID of the GNDivision
     * @param user         User requesting to list the lands
     * @return List of initial lands in the given GNDivision
     */
    public List<Land> getInitialActiveLandsByGNDivision(int gnDivisionId, User user);

    /**
     * Returns list of lands within the given D.S. Division
     *
     * @param dsDivisionId
     * @param user
     * @return List of initial lands in the given D.S. Division
     */
    public List<Land> getInitialActiveLandsByDSDivision(int dsDivisionId, User user);

    /**
     * Find list of lands available for alienation
     *
     * @param user user who requests the Unalienated lands
     * @return Unalienated land list
     */
    public List<Land> getUnalienatedLandList(User user);

    /**
     * Returns list of lands within a given GNDivision which are in detail state
     *
     * @param gnDivisionId Id of the GNDivision
     * @param user         User requesting to list lands
     * @return List of detail lands in the given GNDivision
     */
    public List<Land> getDetailActiveLandsByGNDivision(int gnDivisionId, User user);

    /**
     * Returns list of lands within a given GNDivision which are in Incomplete detail state
     *
     * @param gnDivisionId Id of the GNDivision
     * @param user         User requesting to list lands
     * @return List of detail lands in the given GNDivision
     */
    public List<Land> getIncompleteDetailLandsByGNDivision(int gnDivisionId, User user);

    /**
     * Find all incomplete land records
     *
     * @param user User requesting to find incomplete land records
     * @return List of detailed land records
     */
    public List<Land> getAllIncompleteDetailLands(User user);

    /**
     * Returns list of lands within a given GNDivision which are in Report detail state
     *
     * @param gnDivisionId Id of the GNDivision
     * @param user         User requesting to list lands
     * @return List of detail lands in the given GNDivision
     */
    public List<Land> getDetailLandReportByGNDivision(int gnDivisionId, User user);

    /**
     * Returns list of lands within a given GNDivision which are not ARCHIVED and PENDING for approval
     *
     * @param gnDivisionId Id of the GNDivision
     * @param user         User requesting to list lands
     * @return List of lands
     */
    public List<Land> getActivePendingLandsByGNDivision(int gnDivisionId, User user);

    public List<Land> getRejectedLandsByGNDivision(int gnDivisionId, User user);

    public List<Land> getSubDividedLandsTobeApproveByGNDivision(int gnDivisionId, User user);

    public List<Land> getSubDividedLandsTobeEditByGNDivision(int gnDivisionId, User user);

    public List<Land> getActivePendingLandsByDSDivision(User user);

    /**
     * Returns list of all lands which are PENDING for approval for orip
     * @param dsDivisionId Id of DsDivision
     * @param user User requesting to list lands
     * @return List of lands
     */
    public List<Land> getActivePendingLandsByDSDivisionId(int dsDivisionId, User user);

    public List<Land> getRejectedLandsByDSDivision(User user);

    public List<Land> getSubDividedLandsTobeApproveByDSDivision(User user);

    public List<Land> getSubDividedLandsTobeEditByDSDivision(User user);

    /**
     * Returns list of all lands which are PENDING for approval
     *
     * @param user User requesting to list lands
     * @return List of lands
     */
    public List<Land> getAllActivePendingLands(User user);

    /**
     * Returns list of active lands by state which are not ARCHIVED and located in one of the given GN Divisions.
     *
     * @param user  User requesting the list of lands
     * @param state State of the land record
     * @param mode  Initial or Detailed mode of the land record
     * @return List of Lands available for corresponding GN division List.
     */
    public List<Land> getActiveLandsByGNDivisionListAndState(User user, Land.ApprovalState state, Land.Mode mode);

    /**
     * Returns list of lands within a DSDivision
     *
     * @param dsDivisionId Id of the DSDivision
     * @param user         User requesting to list the lands
     * @return List of lands within the given DSDivision
     */
    public List<Land> getLandsByDSDivision(int dsDivisionId, User user);

    /**
     * Returns list of lands within a DSDivision which are not ARCHIVED
     *
     * @param dsDivisionId Id of the DSDivision
     * @param user         User requesting to list the lands
     * @return List of lands within the given DSDivision
     */
    public List<Land> getActiveLandsByDSDivision(int dsDivisionId, User user);

    /**
     * Returns list of lands within a District
     *
     * @param districtId Id of the District
     * @param user       User requesting to list the lands
     * @return List of lands within the given District
     */
    public List<Land> getLandsByDistrict(int districtId, User user);

    public List<Land> getLandsByDistrictRail(int districtId, User user);


    /**
     * Returns list of lands within a District which are not ARCHIVED
     *
     * @param districtId Id of the District
     * @param user       User requesting to list the lands
     * @return List of lands within the given District
     */
    public List<Land> getActiveLandsByDistrict(int districtId, User user);

    /**
     * Returns list of lands within a Province
     *
     * @param provinceId Id of the Province
     * @param user       User requesting to list the lands
     * @return List of lands within the given Province
     */
    public List<Land> getLandsByProvince(int provinceId, User user);

    /**
     * Returns a land corresponding to the given planNo
     *
     * @param planNo The planNo of the land
     * @param user   User requesting to find the land
     * @return A Land having the given planNo
     */
    public Land getLandByPlanNo(String planNo, User user);

    /**
     * Return Land by id
     *
     * @param id the Land ID
     * @return the Land
     */
    public Land getLandById(long id);

    /**
     * Find a Land by its reference number
     *
     * @param referenceNumber Reference Number of the Land
     * @return Land searched by reference number
     */
    public Land getLandByRef(long referenceNumber);

    /**
     * Return a list of approved, UnAlienated lands by the GN Division
     *
     * @param gnDivisionId Id of the G.N. Division
     * @param user         User requesting to list lands
     * @return List of approved, UnAlienated lands in the given GN Division
     */
    public List<Land> getApprovedUnAlienatedLandsByGNDivision(int gnDivisionId, User user);

    /**
     * Return a list of approved, UnAlienated lands by id
     *
     * @param id Id of the G.N. Division
     * @return Land of approved, UnAlienated lands
     */
    public Land getApprovedUnAlienatedLandById(long id);

    /**
     * Return list of all approved, UnAlienated lands
     *
     * @return List of Approved, UnAlienated lands
     */
    public List<Land> getAllApprovedUnAlienatedLands(User user);

    /**
     * Return a list of approved lands by the GN Division
     *
     * @param gnDivisionId Id of the G.N. Division
     * @param user         User requesting to list lands
     * @return List of approved lands in the given GN Division
     */
    public List<Land> getApprovedLandsByGNDivision(int gnDivisionId, User user);

    public List<Land> getAllApprovedLandsByUser(User user);

    /**
     * Check whether the land has an active Alienation
     *
     * @param landId Id of the land.
     * @return TRUE if the land has an active alienation, FALSE otherwise.
     */
    public Boolean isExistAlienation(long landId);


    /**
     * Return a list of active lands which has the provided land name
     *
     * @param landName Name of the Land to filter
     * @param user     User requesting the search
     * @return List of active lands which has the provided name of the land
     */
    public List<Land> searchActiveLandsByLandName(String landName, User user);

    /**
     * Return a list of active lands which has the provided plan no
     *
     * @param planNo Plan Number to filter
     * @param user   User requesting to search
     * @return List of active lands which has the given planNo
     */
    public List<Land> searchActiveLandsByPlanNo(String planNo, User user);

    /**
     * Return a list of active lands which has the provided lot no
     *
     * @param lotNo Lot Number to filter
     * @param user  User requesting to search
     * @return List of active lands which has the given lotNo
     */
    public List<Land> searchActiveLandsByLotNo(String lotNo, User user);

    /**
     * Return a list of active lands which has the given holder name
     *
     * @param holderName Holder Name to filter
     * @param user       User requesting to search
     * @return List of active lands which has the given holderName
     */
    public List<Land> searchActiveLandsByHolderName(String holderName, User user);

    /**
     * Return all active approved lands
     *
     * @return List of all active approved lands
     */
    public List<Land> searchAllActiveApprovedLands();

    /**
     * Search lands of the DSDivision by Land Name
     *
     * @param landName Name of the land to filter
     * @param user     User requesting to filter lands
     * @return List of lands match the filtering criteria.
     */
    public List<Land> searchActiveLandsOfDSDivisionByLandName(String landName, int dsId, User user);

    /**
     * Search lands of the DSDivision by Land Name
     *
     * @param landName Name of the land to filter
     * @param user     User requesting to filter lands
     * @return List of lands match the filtering criteria.
     */
    public List<Land> searchActiveLandsOfDSDivisionByLandName(String landName, User user);

    /**
     * Search lands of the DSDivision by Plan No
     *
     * @param planNo Plan Number to filter
     * @param user   User requesting to filter lands
     * @return List of lands match the filtering criteria
     */
    public List<Land> searchActiveLandsOfDSDivisionByPlanNo(String planNo, User user);

    /**
     * Search lands of the DSDivision by Lot No
     *
     * @param lotNo Lot Number to be filter
     * @param user  User requesting to filter lands
     * @return List of lands match the filtering criteria
     */
    public List<Land> searchActiveLandsOfDSDivisionByLotNo(String lotNo, User user);

    /**
     * Search lands of DSDivision by Holder Name
     *
     * @param holderName Name of the holder to filter
     * @param user       User requesting to filter lands
     * @return List of lands match the filtering criteria
     */
    public List<Land> searchActiveLandsOfDSDivisionByHolderName(String holderName, User user);

    /**
     * Search all active lands of given D.S. Division
     *
     * @param dsDivisionId Id of the D.S. Division
     * @return List of lands of the D.S. Division
     */
    public List<Land> searchAllActiveApprovedLandsOfDSDivision(int dsDivisionId);

    /**
     * Search all active unalienated lands of given D.S. Division
     *
     * @param dsDivisionId Id of the D.S. Division
     * @return List of lands of the D.S. Division
     */
    public List<Land> searchAllActiveApprovedUnalienatedLandsOfDSDivision(int dsDivisionId);

    public List<Land> searchAllActiveApprovedLandsOfDistrict(int districtId);

    public List<Land> searchChildrenByParentLand(User user, long landId);

    public List<Land> searchAllChildrenByParentLand(User user, long landId);

    public List<Land> searchChildrenByParentReferenceNumber(User user, long landReerenceNumber);

    public List<Land> searchLandByPlanNo(User user, String planNo);

    public List<Land> searchLandByPlanNoAndLotNo(User user, String planNo, String lotNo);

    public List<Land> getAllActivePendingIncompleteLands(User user, int pageNo, int noOfRows);

    public List<Land> getAllActivePendingIncompleteLandsByGNDivision(User user, int gnDivisionId, int pageNo, int noOfRows);

    public List<Land> searchAllLandsReport(int gnDivisionId, String searchBy, Land.AlienationState alienationStateId, int alienationMethodId, int geoTypeId, int pageNo);

    public List<Object[]> getAllLandStatistics(int id, String searchBy, Land.ApprovalState landState, Date fromDate, Date toDate, int language);

    /**
     * Search all lands of the a given dsDivision in User's area by searchText, for users above ORDS
     * @param landName,planNo,lotNo,holderName  search texts
     * @param dsDivisionId   Id of ds division
     * @param pageNo   Used for pagination
     * @return List of lands match the filtering criteria.
     */
    public List<Land> searchAllLandsOfDSDivision(String landName,String planNo,String lotNo,String holderName,int dsDivisionId, int pageNo);

    /**
     * Search all lands of the a given district in User's area by searchText, for users above ORDS
     * @param landName,planNo,lotNo,holderName  search texts
     * @param districtId   Id of district
     * @param pageNo   Used for pagination
     * @return List of lands match the filtering criteria.
     */
    public List<Land> searchAllLandsOfDistrict(String landName,String planNo,String lotNo,String holderName, int districtId, int pageNo);

    /**
     * Search all lands of the DSDivision by searchText for ORDS and lower levels
     * @param landName,planNo,lotNo,holderName  search texts
     * @param user     User requesting to filter lands
     * @param pageNo   Used for pagination
     * @return List of lands match the filtering criteria.
     */
    public List<Land> searchAllLandsOfDSDivisionBySearchText(String landName,String planNo,
                                                             String lotNo,String holderName, User user, int pageNo);

    /**
     * Search all lands of the many DSDivision in User's area by searchText, for users above ORDS
     * @param landName,planNo,lotNo,holderName  search texts
     * @param user     User requesting to filter lands
     * @param pageNo   Used for pagination
     * @return List of lands match the filtering criteria.
     */
    public List<Land> searchAllLandsOfManyDSDivisionsOfUpperLevel(String landName,String planNo,
                                                                  String lotNo,String holderName, User user, int pageNo);

    /**
     * Get the lands in detail mode and not approved yet. Both alienated and unalienated
     * @param user     User
     * @param dsDivision  dsDivision of needed lands
     * @param pageNo   Used for pagination
     * @param noOfRows  Used for pagination
     * @return List all lands in given DsDivision
     */
    public List<Land> getAllActivePendingIncompleteLandsByDsDivision(User user,int dsDivision, int pageNo, int noOfRows) ;

}
